<script setup>
import {computed, onMounted, reactive, useSlots, watch} from 'vue'
import {randomCode} from '@/utils/common/string.js'
import {JBoltApi} from '@/service/request'
import {getServiceEnvConfig} from '~/.env-config'

const slots = useSlots()
const props =
    defineProps({
      /** 是否只用于展示文件列表，不上传 */
      /** 最大允许上传文件数 */
      max: {
        type: Number,
        default: Infinity // 默认不限制
      },
      onlyShow: {
        type: Boolean,
        default: false
      },
      /**上传到哪里，暂时只支持七牛 */
      uploadTo: {
        type: String,
        default: undefined
      },
      /** 使用哪个七牛账号上传，不传则使用默认的，但需要后台配置默认账号 */
      qiniuSn: {
        type: String,
        default: undefined
      },
      /**上传到服务器的路径，支持动态参数，参考 src/utils/common/file.ts中generatePath说明。 */
      savePath: {
        type: String,
        default: undefined
      },
      /** 绑定的数据 */
      modelValue: {
        type: [Array, String],
        required: true
      },
      /** 上传的文件地址是否join成一个字符串，false代表不join返回数组结构，字符串代表join使用的字符，value返回的是join后的一个完整字符串*/
      valueJoin: {
        type: [Boolean, String],
        default: ','
      },
      showFileList: {
        type: Boolean,
        default: true
      }
    })

const emit = defineEmits(['update:modelValue', 'loadFiles'])

const uploadTo = computed(() => {
  const {defaultUploadTo} = getServiceEnvConfig(import.meta.env)
  return props.uploadTo || defaultUploadTo
})

const qiniuSn = computed(() => {
  const {defaultQiniuSn} = getServiceEnvConfig(import.meta.env)
  return props.qiniuSn || defaultQiniuSn
})

const state = reactive({
  fileList: [],
  files: []
})

watch(
    () => props.modelValue,
    () => {
      if (state.fileList.length == 0) {
        syncFileListByModelValue()
      }
    }
)
// 关键修改1：严格限制文件数量
// watch(
//     () => state.fileList,
//     (newList) => {
//       // 自动截断超出限制的文件
//       if (newList.length > props.max) {
//         state.fileList = newList.slice(-props.max) // 只保留最后一个文件
//       }
//     },
//     { deep: true }
// )

async function toUpload({
                          file,
                          onFinish,
                          onError,
                          onProgress
                        }) {


  let url = null
  if (!file.file) return
  try {
    switch (uploadTo.value) {
      case 'qiniu':
        url = await JBoltApi.uploadToQiniu(
            file.file,
            props.savePath,
            qiniuSn.value ?? '',
            ({percent}) => {
              onProgress({percent})
            }
        )
        break
      case 'server':
        url = await JBoltApi.uploadToServer(
            file.file,
            props.savePath,
            ({percent}) => {
              onProgress({percent})
            }
        )
        break
      default:
        throw new Error('不支持的上传类型')
    }
    file.url = url

    console.log('file', file)
    onFinish()

    let fileData = {
      fileName: file.file.name,
      fileType: url.substring(url.lastIndexOf('.') + 1),
      filePath: url,
      fileSize: parseFloat((file.file.size / 1024).toFixed(2))
    }

    state.files.push(fileData)
    emit('loadFiles', state.files)
    state.files = []


    const value = state.fileList
        .filter((item) => item.status == 'finished')
        .map((item) => item.url)


    if (props.valueJoin) {
      console.log('lll', value.join(props.valueJoin))
      emit('update:modelValue', value.join(props.valueJoin))
    } else {
      console.log('ccc', value)
      emit('update:modelValue', value)
    }


  } catch (e) {
    onError()
  }
}

function removeFile({file}) {
  const value = state.fileList
      .filter((item) => item.status == 'finished' && item.id != file.id)
      .map((item) => item.url)
  if (props.valueJoin) {
    emit('update:modelValue', value.join(props.valueJoin))
  } else {
    emit('update:modelValue', value)
  }
}

function syncFileListByModelValue() {
  let value = props.modelValue
  if (typeof value == 'string' && props.valueJoin) {
    value = value.split(props.valueJoin)
  } else if (typeof value == 'string' && !props.valueJoin) {
    throw new Error('valueJoin为false时，modelValue的值不能是字符串')
  }
  state.fileList = value.map((url) => {
    return {
      id: randomCode(8),
      name: url.substring(url.lastIndexOf('/') + 1),
      status: 'finished',
      url: url
    }
  })
}

onMounted(() => {
  if (props.modelValue) {
    syncFileListByModelValue()
  }
})

defineExpose({
  getFileList: () => state.files
})
</script>

<template>
  <n-upload
      v-model:file-list="state.fileList"
      :max = "max"
      :custom-request="toUpload"
      :class="{ notupload: props.onlyShow }"
      @remove="removeFile"
      :showFileList="props.showFileList"
  >
    <template v-for="(_item, key) in slots" :key="key" #[key]="data">
      <slot :name="key" v-bind="data ?? {}"/>
    </template>
  </n-upload>
</template>

<style scoped>
.notupload :deep(.n-upload-trigger) {
  display: none;
}
</style>
